package com.yykj.user.center.server.service.impl;

import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.service.RedisService;
import com.yykj.common.util.GsonUtil;
import com.yykj.common.util.LocalStringUtil;
import com.yykj.order.center.client.feign.OrderCenterFeignClient;
import com.yykj.user.center.server.dto.DoctorDetailDTO;
import com.yykj.user.center.server.dto.UserLoginInfo;
import com.yykj.user.center.server.form.UserLoginForm;
import com.yykj.user.center.server.model.ConsultationInfoOrder;
import com.yykj.user.center.server.model.Doctor;
import com.yykj.user.center.server.model.Evaluation;
import com.yykj.user.center.server.repository.DoctorRepository;
import com.yykj.user.center.server.repository.patient.ConsultationInfoRepository;
import com.yykj.user.center.server.repository.patient.EvaluationRepository;
import com.yykj.user.center.server.repository.patient.RegisterOrderRepository;
import com.yykj.user.center.server.service.DoctorService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.List;

@Slf4j
@Service
public class DoctorServiceImpl implements DoctorService {
    @Autowired
    private EvaluationRepository evaluationRepository;
    @Autowired
    private ConsultationInfoRepository consultationInfoRepository;
    @Autowired
    private RegisterOrderRepository registerOrderRepository;

    @Autowired
    OrderCenterFeignClient orderCenterFeignClient;
    @Override
    public UserLoginInfo login(UserLoginForm form) {
        String token = LocalStringUtil.getUUID();
        Doctor doctor = doctorRepository.findFirstByMobile(form.getMobile());
        if (doctor == null || !doctor.getPassword().equals(LocalStringUtil.encrypt(form.getPassword()))) {
            throw new NormalException(ResultEnums.LOGIN_FAIL);
        }
        UserLoginInfo info = new UserLoginInfo();
        BeanUtils.copyProperties(doctor, info);
        info.setToken(token);
        info.setUserId(doctor.getId());
        redisService.set(token, GsonUtil.toJson(info));

        return info;
    }

    @Override
    public DoctorDetailDTO evaluate(String doctorId) {
        DoctorDetailDTO doctorDetailDTO = new DoctorDetailDTO();
        List<Evaluation> evaluations = evaluationRepository.findAllByDoctorId(doctorId);
        Integer totalScore = 5;
        Integer count = evaluations.size() + 1;
        Integer satisfiedCount=100;//默认满意数
        Integer totalEvaluationCount = 100+evaluations.size();//总评价数
        for (Evaluation evaluation : evaluations) {
            totalScore = totalScore + evaluation.getScore();
            if(evaluation.getScore()==4||evaluation.getScore()==5){
                satisfiedCount=satisfiedCount+1;
            }
        }
        doctorDetailDTO.setScore(String.valueOf((float)(totalScore/count)));
        float num =(float)satisfiedCount/totalEvaluationCount;
        DecimalFormat df = new DecimalFormat("0.0");
        doctorDetailDTO.setFavorableRate(df.format(num));
        int[] states = {2,3};
        Integer receptionCount = consultationInfoRepository.countAllByStateInAndDoctorId(states,doctorId)+100;//接诊数量
        doctorDetailDTO.setReceptionVolume(String.valueOf(receptionCount));
        List<ConsultationInfoOrder> consultationInfoOrders = consultationInfoRepository.findAllByStateInAndDoctorId(states,doctorId);
        Long minutes= 15l;
        Integer receiveCount = consultationInfoOrders.size()+1;
        for(ConsultationInfoOrder consultationInfoOrder:consultationInfoOrders){
            if(consultationInfoOrder.getState()==2 ||consultationInfoOrder.getState()==3){
                LocalDateTime receiveTime = consultationInfoOrder.getReceiveTime();
                LocalDateTime startDateTime = consultationInfoOrder.getStartDatetime();
                if(receiveTime != null && startDateTime != null){
                    Long value = Duration.between(startDateTime,receiveTime).toMinutes();
                    minutes=minutes+value;
                }

            }

        }
        doctorDetailDTO.setResponseTime(String.valueOf(minutes/receiveCount));
        doctorDetailDTO.setTotalPatientNum(consultationInfoRepository.countAllByDoctorId(doctorId));
        LocalDate localDate = LocalDate.now();
        int[] s = {1,2,3};
        LocalDateTime startTime = LocalDateTime.of(
                localDate,
                LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(
                localDate,
                LocalTime.MAX);
        doctorDetailDTO.setTodayConsultationNum(consultationInfoRepository.countAllByReceiveTimeBetweenAndDoctorIdAndStateIn(startTime,endTime,doctorId,s));
//        doctorDetailDTO.setTodayConsultationNum(consultationInfoRepository.countAllByDateAndDoctorIdAndStateIn(localDate,doctorId,s));
        int[] arr = {1,2};
        doctorDetailDTO.setTodayRegisterNum(registerOrderRepository.countByDateAndDoctorIdAndStateIn(localDate,doctorId,arr));
        doctorDetailDTO.setWaitingNum(consultationInfoRepository.countAllByDoctorIdAndState(doctorId,1));
        doctorDetailDTO.setInConsultationNum(consultationInfoRepository.countAllByDoctorIdAndState(doctorId,2));
        int startTimez = dateToTimeStamp(getToday());
        int endTimez = startTimez + 86400;
        doctorDetailDTO.setTodayRemoteConsultationNum(this.orderCenterFeignClient.countByDoctor(doctorId, startTimez, endTimez));
        return doctorDetailDTO;
    }



   /* private Specification<ConsultationInfoOrder> generateSpecification(LocalDate localDate, String doctorId, int[] s){
        return new Specification<ConsultationInfoOrder>() {
            @Override
            public Predicate toPredicate(Root<ConsultationInfoOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                predicateList.add(builder.equal(root.get("doctorId"), doctorId));
                if(localDate != null){


                    LocalDateTime startTime = LocalDateTime.of(localDate, LocalTime.MIN);
                    predicateList.add(builder.greaterThanOrEqualTo(root.get( "addTime"),startTime));

                    LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);
                    predicateList.add(builder.greaterThanOrEqualTo(root.get( "addTime"),startTime));
                }
                if(form.getEndDate()!=null){
                    LocalDateTime endTime = LocalDateTime.of(form.getStartDate(), LocalTime.MAX);
                    predicateList.add(builder.lessThanOrEqualTo(root.get( "addTime"),endTime));
                }

                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        };
    }*/



    private Doctor findById(String id) {
        return doctorRepository.findById(id).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
    }

    private DoctorRepository doctorRepository;

    private RedisService redisService;

    @Autowired
    public void setDoctorRepository(DoctorRepository doctorRepository) {
        this.doctorRepository = doctorRepository;
    }

    @Autowired
    public void setRedisService(RedisService redisService) {
        this.redisService = redisService;
    }

    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();
        LocalDateTime startTime = LocalDateTime.of(
                localDate,
                LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(
                localDate,
                LocalTime.MAX);
        System.out.println(startTime);
    }

    public static String getToday() {
        return getDate(0);
    }
    public static String getDate(int day) {
        Calendar cal = Calendar.getInstance();
        if (day != 0) {
            cal.add(Calendar.DATE, day);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    public static int dateToTimeStamp(String s) {
        return dateToTimeStamp(s, "yyyy-MM-dd");
    }

    public static int dateToTimeStamp(String s, String formatStr) {
        if (StringUtils.isBlank(s)) {
            return 0;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
            return (int) (sdf.parse(s).getTime() / 1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

}
